// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#include <atomic>
#include <cstdlib>

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>

#include "coin2/base/log.h"
#include "coin2/base/rate_limiter.h"

std::atomic<int> push;
std::atomic<int> pop;

void Hello(boost::system::error_code ec) { pop++; }

int main() {
  boost::asio::io_context ioc;
  boost::asio::io_context::strand strand(ioc);
  AsyncLeakyBucket limiter(&strand, 1, 1'000'000'000);  // 1 msg / 1 sec

  auto t1 = std::thread([&] {
    // this prevents ioc.run() to immediately return
    boost::asio::executor_work_guard<decltype(ioc.get_executor())> work {ioc.get_executor()};
    ioc.run();
  });

  auto t2 = std::thread([&] {
    while (true) {
      unsigned int ms;
      rand_r(&ms);
      ms = ms % 1800 + 200;
      std::this_thread::sleep_for(std::chrono::milliseconds(ms));
      push++;
      limiter.PostAsync(&Hello);
    }
  });

  printf("\n");
  while (true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    // printf("\n%d %d\n", push.load(), pop.load());
    printf("\r%d %d", push.load(), pop.load());
    fflush(stdout);
  }

  t1.join();
  t2.join();
}
